package ar.com.mobile.persistence.container;

import java.util.Observable;
import java.util.Observer;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateSessionConfigurator implements Observer {
	/**
	 * Ruta del archivo a tomar la estructura de la tabla
	 */
	private String mapping = null;
	/**
	 * Archivo properties que almacena los datos de la conexion a BBDD
	 */
	private Property urlProperties = null;
	/**
	 * Factory para obtener las conexiones a la BBDD 
	 */
	private SessionFactory sessionFactory = null;
	/**
	 * Flag utilizado como un psedo semaforo, ya que su finalidad es restringir a #getSessionFactory 
	 * si puede obtener la sesion o no. Esto se puede deber a que el archivo se esta utilizando 
	 */
	private volatile boolean lock = false;
	
	/**
	 * Realiza la construccion de la configuracion de la Session de Hibernate
	 * @param mapping Ruta del archivo a tomar la estructura de la tabla
	 * @param urlProperties Archivo properties que almacena los datos de la conexion a BBDD
	 */
	public HibernateSessionConfigurator(String mapping, Property urlProperties) {
		if (mapping == null || mapping.isEmpty())
			throw new IllegalArgumentException("La ruta del archivo mapping esta vacia o es nula");
		
		if (urlProperties == null)
			throw new IllegalArgumentException("Los properties para la conexion son nulos");		
		
		this.mapping = mapping;
		
		this.urlProperties = urlProperties;
		this.urlProperties.addObserver(this);
		
		this.loadProperties();
	}

	@Override
	public void update(Observable o, Object arg) {		
		this.loadProperties();				
	}
	
	/**
	 * Realiza la carga de las propiedades para generar el factory de las conexiones de BBDD
	 */
	protected void loadProperties(){
		lock = true;
		/*
		 * Creamos un nuevo servicio para agregar los recursos que va a usar Hibernate
		 * */
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().configure().buildServiceRegistry();
		/*
		 * Agregamos los XML Mapping para levantar la configuracion de Hibernate 
		 * */
		MetadataSources metadataSources = new MetadataSources(serviceRegistry);		
		metadataSources.addResource(mapping);
		/*
		 * Creamos configuracion para agregar los archivos properties
		 * */
		Configuration configuration = new Configuration();
		configuration.addProperties(urlProperties.getProperties());
		/*
		 * Creamos nuestro objeto Session Factory
		 * */
		this.sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		lock = false;
	}

	/**
	 * Obtiene el Session Factory de la conexion actual
	 * @return Obtiene el Session Factory de la conexion actual
	 */
	public SessionFactory getSessionFactory() {
		while(lock);
		return sessionFactory;		
	}	
}
